//
// Copyright (C) [2020] Futurewei Technologies, Inc.
//
// FORCE-RISCV is licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//  http://www.apache.org/licenses/LICENSE-2.0
//
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR
// FIT FOR A PARTICULAR PURPOSE.
// See the License for the specific language governing permissions and
// limitations under the License.
//

/*  !!! NOTICE !!!
    This file is automatically generated by the script: utils/enum_classes/create_enum_files.py
    Please do not modify this file manually.  Instead, modify the above mentioned script to re-generate this file.
*/

#include <EnumsFPIX.h>

#include <GenException.h>

#include <sstream>

using namespace std;

namespace Force {


  /*!
    Report an unknown enum value of the type name given in enum_type_name parameter, by throwing an EnumTypeError exception.
  */
  static void unknown_enum_value(const string& enum_type_name, unsigned long long value)
  {
    stringstream err_stream;
    err_stream << "Unknown " << enum_type_name << " enum value: " << dec << value;
    throw EnumTypeError(err_stream.str());
  }

  /*!
    Report an unknown enum name of the type name given in enum_type_name parameter, by throwing an EnumTypeError exception.
  */
  static void unknown_enum_name(const string& enum_type_name, const string& enum_name)
  {
    stringstream err_stream;
    err_stream << "Unknown " << enum_type_name << " enum name: " << enum_name;
    throw EnumTypeError(err_stream.str());
  }

  /*!
    Throw an exception if in_str and enum_name are not identical.
  */
  static void validate(const string& specified_enum_name, const string& expected_enum_name, const string& enum_type_name)
  {
    if (specified_enum_name != expected_enum_name) {
      unknown_enum_name(enum_type_name, specified_enum_name);
    }
  }


  unsigned char ESimThreadEventTypeSize = 15;

  const string ESimThreadEventType_to_string(ESimThreadEventType in_enum)
  {
    switch (in_enum) {
    case ESimThreadEventType::START_TEST: return "START_TEST";
    case ESimThreadEventType::END_TEST: return "END_TEST";
    case ESimThreadEventType::RESET: return "RESET";
    case ESimThreadEventType::BOOT_CODE: return "BOOT_CODE";
    case ESimThreadEventType::FIRST_INSTRUCTION: return "FIRST_INSTRUCTION";
    case ESimThreadEventType::PRE_STEP: return "PRE_STEP";
    case ESimThreadEventType::STEP: return "STEP";
    case ESimThreadEventType::POST_STEP: return "POST_STEP";
    case ESimThreadEventType::MEMORY_UPDATE: return "MEMORY_UPDATE";
    case ESimThreadEventType::MMU_EVENT: return "MMU_EVENT";
    case ESimThreadEventType::REGISTER_UPDATE: return "REGISTER_UPDATE";
    case ESimThreadEventType::DELAY: return "DELAY";
    case ESimThreadEventType::INTERRUPT: return "INTERRUPT";
    case ESimThreadEventType::EXCEPTION_EVENT: return "EXCEPTION_EVENT";
    case ESimThreadEventType::UNKNOWN_EVENT: return "UNKNOWN_EVENT";
    default:
      unknown_enum_value("ESimThreadEventType", (unsigned char)(in_enum));
    }
    return "";
  }

  ESimThreadEventType string_to_ESimThreadEventType(const string& in_str)
  {
    string enum_type_name = "ESimThreadEventType";
    size_t size = in_str.size();
    char hash_value = in_str.at(2 < size ? 2 : 2 % size) ^ in_str.at(7 < size ? 7 : 7 % size) ^ in_str.at(9 < size ? 9 : 9 % size);

    switch (hash_value) {
    case 64:
      validate(in_str, "REGISTER_UPDATE", enum_type_name);
      return ESimThreadEventType::REGISTER_UPDATE;
    case 65:
      validate(in_str, "STEP", enum_type_name);
      return ESimThreadEventType::STEP;
    case 66:
      validate(in_str, "UNKNOWN_EVENT", enum_type_name);
      return ESimThreadEventType::UNKNOWN_EVENT;
    case 70:
      validate(in_str, "POST_STEP", enum_type_name);
      return ESimThreadEventType::POST_STEP;
    case 71:
      validate(in_str, "PRE_STEP", enum_type_name);
      return ESimThreadEventType::PRE_STEP;
    case 72:
      validate(in_str, "FIRST_INSTRUCTION", enum_type_name);
      return ESimThreadEventType::FIRST_INSTRUCTION;
    case 73:
      validate(in_str, "BOOT_CODE", enum_type_name);
      return ESimThreadEventType::BOOT_CODE;
    case 77:
      validate(in_str, "INTERRUPT", enum_type_name);
      return ESimThreadEventType::INTERRUPT;
    case 80:
      validate(in_str, "START_TEST", enum_type_name);
      return ESimThreadEventType::START_TEST;
    case 83:
      validate(in_str, "EXCEPTION_EVENT", enum_type_name);
      return ESimThreadEventType::EXCEPTION_EVENT;
    case 84:
      validate(in_str, "RESET", enum_type_name);
      return ESimThreadEventType::RESET;
    case 86:
      validate(in_str, "MMU_EVENT", enum_type_name);
      return ESimThreadEventType::MMU_EVENT;
    case 89:
      validate(in_str, "DELAY", enum_type_name);
      return ESimThreadEventType::DELAY;
    case 92:
      validate(in_str, "MEMORY_UPDATE", enum_type_name);
      return ESimThreadEventType::MEMORY_UPDATE;
    case 94:
      validate(in_str, "END_TEST", enum_type_name);
      return ESimThreadEventType::END_TEST;
    default:
      unknown_enum_name(enum_type_name, in_str);
    }
    return ESimThreadEventType::START_TEST;
  }

  ESimThreadEventType try_string_to_ESimThreadEventType(const string& in_str, bool& okay)
  {
    okay = true;
    size_t size = in_str.size();
    char hash_value = in_str.at(2 < size ? 2 : 2 % size) ^ in_str.at(7 < size ? 7 : 7 % size) ^ in_str.at(9 < size ? 9 : 9 % size);

    switch (hash_value) {
    case 64:
      okay = (in_str == "REGISTER_UPDATE");
      return ESimThreadEventType::REGISTER_UPDATE;
    case 65:
      okay = (in_str == "STEP");
      return ESimThreadEventType::STEP;
    case 66:
      okay = (in_str == "UNKNOWN_EVENT");
      return ESimThreadEventType::UNKNOWN_EVENT;
    case 70:
      okay = (in_str == "POST_STEP");
      return ESimThreadEventType::POST_STEP;
    case 71:
      okay = (in_str == "PRE_STEP");
      return ESimThreadEventType::PRE_STEP;
    case 72:
      okay = (in_str == "FIRST_INSTRUCTION");
      return ESimThreadEventType::FIRST_INSTRUCTION;
    case 73:
      okay = (in_str == "BOOT_CODE");
      return ESimThreadEventType::BOOT_CODE;
    case 77:
      okay = (in_str == "INTERRUPT");
      return ESimThreadEventType::INTERRUPT;
    case 80:
      okay = (in_str == "START_TEST");
      return ESimThreadEventType::START_TEST;
    case 83:
      okay = (in_str == "EXCEPTION_EVENT");
      return ESimThreadEventType::EXCEPTION_EVENT;
    case 84:
      okay = (in_str == "RESET");
      return ESimThreadEventType::RESET;
    case 86:
      okay = (in_str == "MMU_EVENT");
      return ESimThreadEventType::MMU_EVENT;
    case 89:
      okay = (in_str == "DELAY");
      return ESimThreadEventType::DELAY;
    case 92:
      okay = (in_str == "MEMORY_UPDATE");
      return ESimThreadEventType::MEMORY_UPDATE;
    case 94:
      okay = (in_str == "END_TEST");
      return ESimThreadEventType::END_TEST;
    default:
      okay = false;
      return ESimThreadEventType::START_TEST;
    }
    return ESimThreadEventType::START_TEST;
  }


  unsigned char EOptionIndexSize = 15;

  const string EOptionIndex_to_string(EOptionIndex in_enum)
  {
    switch (in_enum) {
    case EOptionIndex::UNKNOWN: return "UNKNOWN";
    case EOptionIndex::CFG: return "CFG";
    case EOptionIndex::HELP: return "HELP";
    case EOptionIndex::LOGLEVEL: return "LOGLEVEL";
    case EOptionIndex::SEED: return "SEED";
    case EOptionIndex::MAX_INSTS_OPT: return "MAX_INSTS_OPT";
    case EOptionIndex::RAILHOUSE_OPT: return "RAILHOUSE_OPT";
    case EOptionIndex::DECODING_OPT: return "DECODING_OPT";
    case EOptionIndex::CORE_NUM_OPT: return "CORE_NUM_OPT";
    case EOptionIndex::CLUSTER_NUM_OPT: return "CLUSTER_NUM_OPT";
    case EOptionIndex::THREADS_PER_CPU_OPT: return "THREADS_PER_CPU_OPT";
    case EOptionIndex::PA_SIZE_OPT: return "PA_SIZE_OPT";
    case EOptionIndex::EXIT_LOOP_OPT: return "EXIT_LOOP_OPT";
    case EOptionIndex::PLUGIN: return "PLUGIN";
    case EOptionIndex::PLUGINS_OPTIONS: return "PLUGINS_OPTIONS";
    default:
      unknown_enum_value("EOptionIndex", (unsigned char)(in_enum));
    }
    return "";
  }

  EOptionIndex string_to_EOptionIndex(const string& in_str)
  {
    string enum_type_name = "EOptionIndex";
    size_t size = in_str.size();
    char hash_value = in_str.at(3 < size ? 3 : 3 % size) ^ in_str.at(10 < size ? 10 : 10 % size);

    switch (hash_value) {
    case 0:
      validate(in_str, "UNKNOWN", enum_type_name);
      return EOptionIndex::UNKNOWN;
    case 1:
      validate(in_str, "SEED", enum_type_name);
      return EOptionIndex::SEED;
    case 3:
      validate(in_str, "RAILHOUSE_OPT", enum_type_name);
      return EOptionIndex::RAILHOUSE_OPT;
    case 5:
      validate(in_str, "CFG", enum_type_name);
      return EOptionIndex::CFG;
    case 7:
      validate(in_str, "PA_SIZE_OPT", enum_type_name);
      return EOptionIndex::PA_SIZE_OPT;
    case 11:
      validate(in_str, "LOGLEVEL", enum_type_name);
      return EOptionIndex::LOGLEVEL;
    case 14:
      validate(in_str, "PLUGIN", enum_type_name);
      return EOptionIndex::PLUGIN;
    case 16:
      validate(in_str, "MAX_INSTS_OPT", enum_type_name);
      return EOptionIndex::MAX_INSTS_OPT;
    case 19:
      validate(in_str, "PLUGINS_OPTIONS", enum_type_name);
      return EOptionIndex::PLUGINS_OPTIONS;
    case 21:
      validate(in_str, "CORE_NUM_OPT", enum_type_name);
      return EOptionIndex::CORE_NUM_OPT;
    case 23:
      validate(in_str, "THREADS_PER_CPU_OPT", enum_type_name);
      return EOptionIndex::THREADS_PER_CPU_OPT;
    case 27:
      validate(in_str, "EXIT_LOOP_OPT", enum_type_name);
      return EOptionIndex::EXIT_LOOP_OPT;
    case 28:
      validate(in_str, "HELP", enum_type_name);
      return EOptionIndex::HELP;
    case 30:
      validate(in_str, "CLUSTER_NUM_OPT", enum_type_name);
      return EOptionIndex::CLUSTER_NUM_OPT;
    case 31:
      validate(in_str, "DECODING_OPT", enum_type_name);
      return EOptionIndex::DECODING_OPT;
    default:
      unknown_enum_name(enum_type_name, in_str);
    }
    return EOptionIndex::UNKNOWN;
  }

  EOptionIndex try_string_to_EOptionIndex(const string& in_str, bool& okay)
  {
    okay = true;
    size_t size = in_str.size();
    char hash_value = in_str.at(3 < size ? 3 : 3 % size) ^ in_str.at(10 < size ? 10 : 10 % size);

    switch (hash_value) {
    case 0:
      okay = (in_str == "UNKNOWN");
      return EOptionIndex::UNKNOWN;
    case 1:
      okay = (in_str == "SEED");
      return EOptionIndex::SEED;
    case 3:
      okay = (in_str == "RAILHOUSE_OPT");
      return EOptionIndex::RAILHOUSE_OPT;
    case 5:
      okay = (in_str == "CFG");
      return EOptionIndex::CFG;
    case 7:
      okay = (in_str == "PA_SIZE_OPT");
      return EOptionIndex::PA_SIZE_OPT;
    case 11:
      okay = (in_str == "LOGLEVEL");
      return EOptionIndex::LOGLEVEL;
    case 14:
      okay = (in_str == "PLUGIN");
      return EOptionIndex::PLUGIN;
    case 16:
      okay = (in_str == "MAX_INSTS_OPT");
      return EOptionIndex::MAX_INSTS_OPT;
    case 19:
      okay = (in_str == "PLUGINS_OPTIONS");
      return EOptionIndex::PLUGINS_OPTIONS;
    case 21:
      okay = (in_str == "CORE_NUM_OPT");
      return EOptionIndex::CORE_NUM_OPT;
    case 23:
      okay = (in_str == "THREADS_PER_CPU_OPT");
      return EOptionIndex::THREADS_PER_CPU_OPT;
    case 27:
      okay = (in_str == "EXIT_LOOP_OPT");
      return EOptionIndex::EXIT_LOOP_OPT;
    case 28:
      okay = (in_str == "HELP");
      return EOptionIndex::HELP;
    case 30:
      okay = (in_str == "CLUSTER_NUM_OPT");
      return EOptionIndex::CLUSTER_NUM_OPT;
    case 31:
      okay = (in_str == "DECODING_OPT");
      return EOptionIndex::DECODING_OPT;
    default:
      okay = false;
      return EOptionIndex::UNKNOWN;
    }
    return EOptionIndex::UNKNOWN;
  }


  unsigned char EOperandTypeSize = 3;

  const string EOperandType_to_string(EOperandType in_enum)
  {
    switch (in_enum) {
    case EOperandType::Register: return "Register";
    case EOperandType::GPR: return "GPR";
    case EOperandType::VECREG: return "VECREG";
    default:
      unknown_enum_value("EOperandType", (unsigned char)(in_enum));
    }
    return "";
  }

  EOperandType string_to_EOperandType(const string& in_str)
  {
    string enum_type_name = "EOperandType";
    char hash_value = in_str.at(0);

    switch (hash_value) {
    case 71:
      validate(in_str, "GPR", enum_type_name);
      return EOperandType::GPR;
    case 82:
      validate(in_str, "Register", enum_type_name);
      return EOperandType::Register;
    case 86:
      validate(in_str, "VECREG", enum_type_name);
      return EOperandType::VECREG;
    default:
      unknown_enum_name(enum_type_name, in_str);
    }
    return EOperandType::Register;
  }

  EOperandType try_string_to_EOperandType(const string& in_str, bool& okay)
  {
    okay = true;
    char hash_value = in_str.at(0);

    switch (hash_value) {
    case 71:
      okay = (in_str == "GPR");
      return EOperandType::GPR;
    case 82:
      okay = (in_str == "Register");
      return EOperandType::Register;
    case 86:
      okay = (in_str == "VECREG");
      return EOperandType::VECREG;
    default:
      okay = false;
      return EOperandType::Register;
    }
    return EOperandType::Register;
  }


  unsigned char EAccessAgeTypeSize = 3;

  const string EAccessAgeType_to_string(EAccessAgeType in_enum)
  {
    switch (in_enum) {
    case EAccessAgeType::Invalid: return "Invalid";
    case EAccessAgeType::Read: return "Read";
    case EAccessAgeType::Write: return "Write";
    default:
      unknown_enum_value("EAccessAgeType", (unsigned char)(in_enum));
    }
    return "";
  }

  EAccessAgeType string_to_EAccessAgeType(const string& in_str)
  {
    string enum_type_name = "EAccessAgeType";
    char hash_value = in_str.at(0);

    switch (hash_value) {
    case 73:
      validate(in_str, "Invalid", enum_type_name);
      return EAccessAgeType::Invalid;
    case 82:
      validate(in_str, "Read", enum_type_name);
      return EAccessAgeType::Read;
    case 87:
      validate(in_str, "Write", enum_type_name);
      return EAccessAgeType::Write;
    default:
      unknown_enum_name(enum_type_name, in_str);
    }
    return EAccessAgeType::Invalid;
  }

  EAccessAgeType try_string_to_EAccessAgeType(const string& in_str, bool& okay)
  {
    okay = true;
    char hash_value = in_str.at(0);

    switch (hash_value) {
    case 73:
      okay = (in_str == "Invalid");
      return EAccessAgeType::Invalid;
    case 82:
      okay = (in_str == "Read");
      return EAccessAgeType::Read;
    case 87:
      okay = (in_str == "Write");
      return EAccessAgeType::Write;
    default:
      okay = false;
      return EAccessAgeType::Invalid;
    }
    return EAccessAgeType::Invalid;
  }


  unsigned char EDependencyTypeSize = 2;

  const string EDependencyType_to_string(EDependencyType in_enum)
  {
    switch (in_enum) {
    case EDependencyType::OnSource: return "OnSource";
    case EDependencyType::OnTarget: return "OnTarget";
    default:
      unknown_enum_value("EDependencyType", (unsigned char)(in_enum));
    }
    return "";
  }

  EDependencyType string_to_EDependencyType(const string& in_str)
  {
    string enum_type_name = "EDependencyType";
    size_t size = in_str.size();
    char hash_value = in_str.at(2 < size ? 2 : 2 % size);

    switch (hash_value) {
    case 83:
      validate(in_str, "OnSource", enum_type_name);
      return EDependencyType::OnSource;
    case 84:
      validate(in_str, "OnTarget", enum_type_name);
      return EDependencyType::OnTarget;
    default:
      unknown_enum_name(enum_type_name, in_str);
    }
    return EDependencyType::OnSource;
  }

  EDependencyType try_string_to_EDependencyType(const string& in_str, bool& okay)
  {
    okay = true;
    size_t size = in_str.size();
    char hash_value = in_str.at(2 < size ? 2 : 2 % size);

    switch (hash_value) {
    case 83:
      okay = (in_str == "OnSource");
      return EDependencyType::OnSource;
    case 84:
      okay = (in_str == "OnTarget");
      return EDependencyType::OnTarget;
    default:
      okay = false;
      return EDependencyType::OnSource;
    }
    return EDependencyType::OnSource;
  }

}
